{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "djUvWu41mtXa"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "su2RaORHpReL"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Jp9JqDRqxVWU"
      },
      "source": [
        "# Overview"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "b8eIstD1wuol"
      },
      "source": [
        "This is a simple demo of how to use Mesh plugin for TensorBoard. The demo will load static triangulated mesh (in PLY format), create a mesh summary with it and then display in TensorBoard."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PPRzYdGDaVUH"
      },
      "source": [
        "# Setup Imports"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1a_Qfm_OZrtf"
      },
      "outputs": [],
      "source": [
        "from __future__ import absolute_import\n",
        "from __future__ import division\n",
        "from __future__ import print_function\n",
        "\n",
        "# Uninstall tensorboard and tensorflow\n",
        "!pip uninstall -q -y tensorboard\n",
        "!pip uninstall -q -y tensorflow\n",
        "# Install nightly TensorFlow with nightly TensorBoard.\n",
        "!pip install tf-nightly\n",
        "# Install trimesh lib to read .PLY files.\n",
        "!pip freeze | grep -qF 'trimesh==' || pip install trimesh\n",
        "\n",
        "%load_ext tensorboard\n",
        "\n",
        "import os\n",
        "\n",
        "import numpy as np\n",
        "import tensorflow as tf\n",
        "import trimesh\n",
        "import tensorboard\n",
        "\n",
        "from tensorboard.plugins.mesh import summary as mesh_summary\n",
        "\n",
        "sample_mesh = 'https://storage.googleapis.com/tensorflow-graphics/tensorboard/test_data/ShortDance07_a175_00001.ply'\n",
        "log_dir = '/tmp/mesh_demo'\n",
        "batch_size = 1\n",
        "\n",
        "!rm -rf /tmp/mesh_demo"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GeQsREQFabgx"
      },
      "source": [
        "# Read sample .PLY files"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "WEJe1bebajDX"
      },
      "outputs": [],
      "source": [
        "# Camera and scene configuration.\n",
        "config_dict = {\n",
        "    'camera': {'cls': 'PerspectiveCamera', 'fov': 75},\n",
        "    'lights': [\n",
        "        {\n",
        "          'cls': 'AmbientLight', \n",
        "          'color': '#ffffff',\n",
        "          'intensity': 0.75,\n",
        "        }, {\n",
        "          'cls': 'DirectionalLight',\n",
        "          'color': '#ffffff',\n",
        "          'intensity': 0.75,\n",
        "          'position': [0, -1, 2],\n",
        "        }],\n",
        "    'material': {\n",
        "      'cls': 'MeshStandardMaterial',\n",
        "      'roughness': 1,\n",
        "      'metalness': 0\n",
        "    }\n",
        "}\n",
        "\n",
        "# Read all sample PLY files.\n",
        "mesh = trimesh.load_remote(sample_mesh)    \n",
        "vertices = np.array(mesh.vertices)\n",
        "# Currently only supports RGB colors.\n",
        "colors = np.array(mesh.visual.vertex_colors[:, :3])\n",
        "faces = np.array(mesh.faces)\n",
        "\n",
        "# Add batch dimension, so our data will be of shape BxNxC.\n",
        "vertices = np.expand_dims(vertices, 0)\n",
        "colors = np.expand_dims(colors, 0)\n",
        "faces = np.expand_dims(faces, 0)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5N_SfPiia0zn"
      },
      "source": [
        "# Create summaries and session"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "id": "ODi7QiLPa1AR"
      },
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "WARNING: Logging before flag parsing goes to stderr.\n",
            "W0509 14:00:39.764862 140689019053952 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/dist-packages/tensorboard/plugins/mesh/summary.py:59: The name tf.summary.tensor_summary is deprecated. Please use tf.compat.v1.summary.tensor_summary instead.\n",
            "\n",
            "W0509 14:00:39.776251 140689019053952 deprecation_wrapper.py:119] From /usr/local/lib/python3.6/dist-packages/tensorboard/plugins/mesh/summary.py:125: The name tf.summary.merge is deprecated. Please use tf.compat.v1.summary.merge instead.\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Create data placeholders of the same shape as data itself.\n",
        "vertices_tensor = tf.placeholder(tf.float32, vertices.shape)\n",
        "faces_tensor = tf.placeholder(tf.int32, faces.shape)\n",
        "colors_tensor = tf.placeholder(tf.int32, colors.shape)\n",
        "\n",
        "meshes_summary = mesh_summary.op(\n",
        "    'mesh_color_tensor', vertices=vertices_tensor, faces=faces_tensor,\n",
        "    colors=colors_tensor, config_dict=config_dict)\n",
        "\n",
        "# Create summary writer and session.\n",
        "writer = tf.summary.FileWriter(log_dir)\n",
        "sess = tf.Session()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wUVbZ-I-a76w"
      },
      "source": [
        "# Run the model, save summaries to disk"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "sBcDE1jRa8FZ"
      },
      "outputs": [],
      "source": [
        "summaries = sess.run([meshes_summary], feed_dict={\n",
        "    vertices_tensor: vertices,\n",
        "    faces_tensor: faces,\n",
        "    colors_tensor: colors,\n",
        "})\n",
        "# Save summaries.\n",
        "for summary in summaries:\n",
        "  writer.add_summary(summary)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "huft1mbibF21"
      },
      "source": [
        "# TensorBoard"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "4rLrgb3EbGAp"
      },
      "outputs": [],
      "source": [
        "%tensorboard --logdir=/tmp/mesh_demo"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "Mesh_Plugin_Tensorboard.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
